package com.assjirc.irc;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import com.assjirc.enums.ReturnStatus;
import com.assjirc.interfaces.GuiEventHandler;
import com.assjirc.pircbothack.IrcException;
import com.assjirc.pircbothack.NickAlreadyInUseException;
import com.assjirc.pircbothack.PircBot;
import com.assjirc.pircbothack.User;

public class IrcManager extends PircBot {

	public static String CHANNEL_PATTERN = "^#[a-zA-Z0-9]+$";

	private GuiEventHandler guiEventHandler;

	public static String FUNCTION_CHAR = "/";

	public static Channel currentChannel;

	private static Set<Channel> channels;

	public IrcManager(GuiEventHandler guiEventHandler) {
		this.guiEventHandler = guiEventHandler;
		channels = new HashSet<Channel>();
	}

	public ReturnStatus joinServer(String server, int port, String nick, String password) {
		this.setLogin(nick);
		this.setName(nick);
		try {
			this.connect(server, port, password);
			return ReturnStatus.SUCCESS;
		} catch (NickAlreadyInUseException e) {
			return ReturnStatus.NICK_ALREADY_IN_USE;
		} catch (IOException e) {
			// TODO implement logging
			e.printStackTrace();
		} catch (IrcException e) {
			// TODO implement logging
			e.printStackTrace();
		}
		return ReturnStatus.FAILURE;
	}

	public ReturnStatus partChannelAndReturn(String channel, String reason) {
		try {
			if (findChannelByName(channel) == null) {
				System.out.println("error parting: not in room");
				return ReturnStatus.NOT_IN_CHANNEL;
			} else {
				if (reason != null) {
					this.partChannel(channel, reason);
				} else {
					this.partChannel(channel);
				}
				channels.remove(findChannelByName(channel));
			}
			return ReturnStatus.SUCCESS;
		} catch (Exception e) {
			System.out.println("error parting: failure");
			return ReturnStatus.FAILURE;
		}
	}

	public ReturnStatus joinChannelAndReturn(String channel, String password) {
		try {
			if (channel != null && channel.matches(CHANNEL_PATTERN)) {
				if (this.findChannelByName(channel) != null) {
					return ReturnStatus.ALREADY_IN_CHANNEL;
				}
				this.joinChannel(channel, password);
				channels.add(new Channel(channel));
				return ReturnStatus.SUCCESS;
			}
			return ReturnStatus.INVALID;
		} catch (Exception e) {
			// TODO implement logging
			return ReturnStatus.FAILURE;
		}
	}

	public Channel findChannelByName(String name) {
		if (name != null) {
			for (Channel channel : channels) {
				if (channel.getName().equalsIgnoreCase(name)) {
					return channel;
				}
			}
		}
		return null;
	}

	@Override
	protected void onMessage(String channel, String sender, String login, String hostname, String message) {
		Message tmp = new Message(channel, sender, login, hostname, message);
		guiEventHandler.onMessage(tmp);
	}

	@Override
	protected void onAction(String sender, String login, String hostname, String target, String action) {
		Message tmp = new Message(target, sender, login, hostname, action);
		guiEventHandler.onAction(tmp);
	}

	@Override
	protected void onChannelInfo(String channel, int userCount, String topic) {
		guiEventHandler.onChannelInfo(channel, userCount, topic);
	}

	@Override
	protected void onUserList(String channel, User[] users) {
		guiEventHandler.onUserList(channel, users);
	}

	@Override
	protected void onTopic(String channel, String topic, String setBy, long date, boolean changed) {
		Channel chan = findChannelByName(channel);
		if (chan != null) {
			chan.setTopic(topic);
		}
		guiEventHandler.onTopic(channel, topic, setBy, date, changed);
	}

	@Override
	protected void onJoin(String channel, String sender, String login, String hostname) {
		guiEventHandler.onJoin(channel, sender, login, hostname);
	}

	@Override
	protected void onPart(String channel, String sender, String login, String hostname) {
		guiEventHandler.onPart(channel, sender, login, hostname);
	}

	@Override
	protected void onQuit(String sourceNick, String sourceLogin, String sourceHostname, String reason) {
		guiEventHandler.onQuit(sourceNick, sourceLogin, sourceHostname, reason);
	}
}
